From 10b7bf98cbcfe75cc7e0c5c22be3ddc41c73e291 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 30 May 2005 21:15:54 +0000 Subject: [PATCH] bitkeeper revision 1.1599 (429b828aL4XKwdaPjLGObI37F4hwiw) By default do not enable local APIC if disabled by the BIOS. This matches Linux behaviour and ought to improve stability on buggy hardware/firmware (laptops in particular). As in Linux, you can forcibly enable the APIC with 'lapic' command-line option, or forcibly ignore it with 'nolapic'. Signed-off-by: Keir Fraser --- docs/src/user.tex | 26 +++++++++++------- xen/arch/x86/apic.c | 51 +++++++++++++++++++++++++++++++++++- xen/arch/x86/genapic/probe.c | 36 +++++++++---------------- xen/arch/x86/setup.c | 19 +++----------- 4 files changed, 83 insertions(+), 49 deletions(-) diff --git a/docs/src/user.tex b/docs/src/user.tex index 594ef59135..e2988ec2a0 100644 --- a/docs/src/user.tex +++ b/docs/src/user.tex @@ -1770,14 +1770,25 @@ editing \path{grub.conf}. Select the CPU scheduler Xen should use. The current possibilities are `bvt' (default), `atropos' and `rrobin'. For more information see Section~\ref{s:sched}. -\end{description} -In addition, the following platform-specific options may be specified -on the Xen command line. Since domain 0 shares responsibility for -booting the platform, Xen will automatically propagate these options -to its command line. +\item [apic\_verbosity=debug,verbose ] + Print more detailed information about local APIC and IOAPIC configuration. + +\item [lapic ] + Force use of local APIC even when left disabled by uniprocessor BIOS. + +\item [nolapic ] + Ignore local APIC in a uniprocessor system, even if enabled by the BIOS. + +\item [apic=bigsmp,default,es7000,summit ] + Specify NUMA platform. This can usually be probed automatically. -These options are taken from Linux's command-line syntax with +\end{description} + +In addition, the following options may be specified on the Xen command +line. Since domain 0 shares responsibility for booting the platform, +Xen will automatically propagate these options to its command +line. These options are taken from Linux's command-line syntax with unchanged semantics. \begin{description} @@ -1792,9 +1803,6 @@ unchanged semantics. Instruct Xen (and domain 0) to ignore any IOAPICs that are present in the system, and instead continue to use the legacy PIC. -\item [apic=debug,verbose ] - Print more detailed information about local APIC and IOAPIC configuration. - \end{description} \section{XenLinux Boot Options} diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 9857365074..684a180540 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -99,6 +99,13 @@ void clear_local_APIC(void) apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED); } +/* lets not touch this if we didn't frob it */ +#ifdef CONFIG_X86_MCE_P4THERMAL + if (maxlvt >= 5) { + v = apic_read(APIC_LVTTHMR); + apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED); + } +#endif /* * Clean APIC state for other OSs: */ @@ -110,6 +117,10 @@ void clear_local_APIC(void) if (maxlvt >= 4) apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); +#ifdef CONFIG_X86_MCE_P4THERMAL + if (maxlvt >= 5) + apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED); +#endif v = GET_APIC_VERSION(apic_read(APIC_LVR)); if (APIC_INTEGRATED(v)) { /* !82489DX */ if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */ @@ -134,6 +145,7 @@ void __init connect_bsp_APIC(void) outb(0x70, 0x22); outb(0x01, 0x23); } + enable_apic_mode(); } void disconnect_bsp_APIC(void) @@ -448,20 +460,45 @@ void __init setup_local_APIC (void) * Original code written by Keir Fraser. */ +/* + * Knob to control our willingness to enable the local APIC. + */ +int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ + +static void __init lapic_disable(char *str) +{ + enable_local_apic = -1; + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); +} +custom_param("nolapic", lapic_disable); + +static void __init lapic_enable(char *str) +{ + enable_local_apic = 1; +} +custom_param("lapic", lapic_enable); + static void __init apic_set_verbosity(char *str) { if (strcmp("debug", str) == 0) apic_verbosity = APIC_DEBUG; else if (strcmp("verbose", str) == 0) apic_verbosity = APIC_VERBOSE; + else + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic_verbosity=verbose or apic_verbosity=debug", str); } -custom_param("apic", apic_set_verbosity); +custom_param("apic_verbosity", apic_set_verbosity); static int __init detect_init_APIC (void) { u32 h, l, features; extern void get_cpu_vendor(struct cpuinfo_x86*); + /* Disabled by kernel option? */ + if (enable_local_apic < 0) + return -1; + /* Workaround for us being called before identify_cpu(). */ get_cpu_vendor(&boot_cpu_data); @@ -481,6 +518,15 @@ static int __init detect_init_APIC (void) } if (!cpu_has_apic) { + /* + * Over-ride BIOS and try to enable the local + * APIC only if "lapic" specified. + */ + if (enable_local_apic <= 0) { + printk("Local APIC disabled by BIOS -- " + "you can enable it with \"lapic\"\n"); + return -1; + } /* * Some BIOSes disable the local APIC in the * APIC_BASE MSR. This can only be done in @@ -951,6 +997,9 @@ asmlinkage void smp_error_interrupt(struct cpu_user_regs *regs) */ int __init APIC_init_uniprocessor (void) { + if (enable_local_apic < 0) + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); + if (!smp_found_config && !cpu_has_apic) return -1; diff --git a/xen/arch/x86/genapic/probe.c b/xen/arch/x86/genapic/probe.c index 9645f46654..a3a94fe753 100644 --- a/xen/arch/x86/genapic/probe.c +++ b/xen/arch/x86/genapic/probe.c @@ -19,7 +19,7 @@ extern struct genapic apic_bigsmp; extern struct genapic apic_es7000; extern struct genapic apic_default; -struct genapic *genapic = &apic_default; +struct genapic *genapic; struct genapic *apic_probe[] __initdata = { &apic_summit, @@ -29,38 +29,28 @@ struct genapic *apic_probe[] __initdata = { NULL, }; -void __init generic_apic_probe(char *command_line) +static void __init genapic_apic_force(char *str) +{ + int i; + for (i = 0; apic_probe[i]; i++) + if (!strcmp(apic_probe[i]->name, str)) + genapic = apic_probe[i]; +} +custom_param("apic", genapic_apic_force); + +void __init generic_apic_probe(void) { - char *s; int i; - int changed = 0; + int changed = (genapic != NULL); - s = strstr(command_line, "apic="); - if (s && (s == command_line || isspace(s[-1]))) { - char *p = strchr(s, ' '), old; - if (!p) - p = strchr(s, '\0'); - old = *p; - *p = 0; - for (i = 0; !changed && apic_probe[i]; i++) { - if (!strcmp(apic_probe[i]->name, s+5)) { - changed = 1; - genapic = apic_probe[i]; - } - } - if (!changed) - printk(KERN_ERR "Unknown genapic `%s' specified.\n", s); - *p = old; - } for (i = 0; !changed && apic_probe[i]; i++) { if (apic_probe[i]->probe()) { changed = 1; genapic = apic_probe[i]; } } - /* Not visible without early console */ if (!changed) - panic("Didn't find an APIC driver"); + genapic = &apic_default; printk(KERN_INFO "Using APIC driver %s\n", genapic->name); } diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 2d16e56a52..d1d89ef4a3 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -21,7 +21,7 @@ #include extern void dmi_scan_machine(void); -extern void generic_apic_probe(char *); +extern void generic_apic_probe(void); /* * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the @@ -67,8 +67,6 @@ boolean_param("acpi_skip_timer_override", acpi_skip_timer_override); extern int skip_ioapic_setup; boolean_param("noapic", skip_ioapic_setup); -static char *xen_cmdline; - int early_boot = 1; int ht_per_core = 1; @@ -179,8 +177,7 @@ static void __init start_of_day(void) dmi_scan_machine(); - if ( xen_cmdline != NULL ) - generic_apic_probe(xen_cmdline); + generic_apic_probe(); acpi_boot_table_init(); acpi_boot_init(); @@ -251,10 +248,7 @@ void __init __start_xen(multiboot_info_t *mbi) /* Parse the command-line options. */ if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) - { - xen_cmdline = __va(mbi->cmdline); - cmdline_parse(xen_cmdline); - } + cmdline_parse(__va(mbi->cmdline)); /* Must do this early -- e.g., spinlocks rely on get_current(). */ set_current(&idle0_exec_domain); @@ -436,13 +430,6 @@ void __init __start_xen(multiboot_info_t *mbi) strcat(cmdline, " acpi="); strcat(cmdline, acpi_param); } - if ( !strstr(cmdline, "apic=") ) - { - if ( apic_verbosity == APIC_VERBOSE ) - strcat(cmdline, " apic=verbose"); - else if ( apic_verbosity == APIC_DEBUG ) - strcat(cmdline, " apic=debug"); - } } /* -- 2.30.2